package _2_observer

import (
	"fmt"
	"sync"
	"time"
)

type Observable interface {
	Register(observer Observer) error
	Remove(observer Observer) error
	Notify(message interface{})
}

type Observer interface {
	update(observable Observable, message interface{})
}

type Server struct {
	observers []Observer
	mutex     sync.Mutex
}

func (s *Server) Register(observer Observer) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	s.observers = append(s.observers, observer)
	return nil
}

func (s *Server) Remove(observer Observer) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for i, ob := range s.observers {
		if ob == observer {
			s.observers = append(s.observers[:i], s.observers[i+1:]...)
		}
	}
	return nil
}

func (s *Server) Notify(message interface{}) {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for _, ob := range s.observers {
		ob.update(s, message)
	}
}

type DeliveryCompleteEvent struct {
	orderId      string
	completeTime time.Time
}

type DeliveryObserver struct {
}

func (receiver DeliveryObserver) complete(event DeliveryCompleteEvent) {
	fmt.Println("completed delivery:", event.orderId, event.completeTime)
}

func (receiver DeliveryObserver) update(observable Observable, message interface{}) {
	event := message.(DeliveryCompleteEvent)
	receiver.complete(event)
}
